package com.yq.ylmall.user.controller;

import com.alibaba.fastjson.JSON;
import com.yq.ylmall.common.utils.JwtUtils;
import com.yq.ylmall.dto.user.UserLoginDto;
import com.yq.ylmall.dto.user.UserRegisterDto;
import com.yq.ylmall.exception.ServiceException;
import com.yq.ylmall.model.user.UserAddress;
import com.yq.ylmall.model.user.UserInfo;
import com.yq.ylmall.result.Result;
import com.yq.ylmall.result.ResultCode;
import com.yq.ylmall.user.service.IUserAddressService;
import com.yq.ylmall.user.service.IUserInfoService;
import com.yq.ylmall.utils.SendSMSUtil;
import com.yq.ylmall.vo.user.UserBaseDetailVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Project: yourlife
 * @Name: UserLoginController
 * @Author: Jack_Li
 * @Date: 2024/6/16 16:51
 */

@Slf4j
@Api(tags = "用户登录接口")
@RestController
@CrossOrigin
@RequestMapping("/api/user")
public class UserLoginController {

    @Resource
    private IUserInfoService userInfoService;

    @Resource
    private IUserAddressService userAddressService;

    @Resource
    private RedisTemplate<String , String> redisTemplate;

    @ApiOperation("登录方法")
    @PostMapping("/login")
    public Result login(@RequestBody UserLoginDto dto){
        UserInfo userInfo = userInfoService.getUserInfoUsername(dto.getUsername());
        //未找到登录账号
        if (userInfo == null){
            return Result.fail(ResultCode.FETCH_USERINFO_ERROR);
        }
        //账号密码错误
        String passwordWithMd5 = getMD5Password(dto.getPassword());
        if (!userInfo.getPassword().equals(passwordWithMd5)){
            return Result.fail(ResultCode.INCORRECT_USERNAME_OR_PASSWORD);
        }
        //账号被停用
        if (userInfo.getStatus().intValue() == 0){
            return Result.fail(ResultCode.FETCH_USERINFO_ERROR);
        }

        UserBaseDetailVo userBaseDetail = new UserBaseDetailVo();
        BeanUtils.copyProperties(userInfo, userBaseDetail);
        List<UserAddress> userAddressList = userAddressService.getAddressByUserId(userInfo.getId());
        if(userAddressList.size() > 0) {
            userBaseDetail.setUserAddressList(userAddressList);
        }
        // 生成令牌，保存数据到Redis中
        String token = JwtUtils.createAdminToken(userInfo.getId());
        // TODO redis测试 token 设置为 7天
        redisTemplate.opsForValue().set("user:login:" + token , JSON.toJSONString(userBaseDetail), 7 , TimeUnit.DAYS);
        return Result.ok(token);
    }

    @ApiOperation("注册方法")
    @PostMapping("/register")
    public Result registor(@RequestBody UserRegisterDto dto){
        //将密码加密
        String passwordWithMd5=getMD5Password(dto.getPassword());
        dto.setPassword(passwordWithMd5);

        userInfoService.saveUserInfo(dto);
        return Result.ok();
    }

    @ApiOperation("短信登录")
    @PostMapping("/login/code")
    public Result codeLogin(@RequestBody UserLoginDto dto){
        UserInfo userInfo=userInfoService.getUserInfoUsername(dto.getUsername());

        //未找到登录账号
        if (userInfo==null){
            throw new ServiceException(ResultCode.FETCH_USERINFO_ERROR);
        }
        String getPhone = userInfo.getPhone();
        String getCode = dto.getPassword();
        String code = (String) redisTemplate.opsForValue().get("code:"+getCode);
        String phone = (String) redisTemplate.opsForValue().get("phone:"+getPhone);
        System.out.println("code:"+code);
        System.out.println("phone:"+phone);
        if (getCode.equals(code) & getPhone.equals(phone)){
            // 生成令牌，保存数据到Redis中
            String token = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().set("user:login:" + token , JSON.toJSONString(userInfo) , 7 , TimeUnit.DAYS);
        }else {
            throw new ServiceException(ResultCode.INCORRECT_USERNAME_OR_PASSWORD);
        }
        return Result.ok();
    }

    @ApiOperation("短信发送")
    @PostMapping("/sendCode")
    public Result sendCode(@RequestBody UserLoginDto dto) throws IOException {
        UserInfo userInfo=userInfoService.getUserInfoUsername(dto.getUsername());
        //未找到登录账号
        if (userInfo==null){
            throw new ServiceException(ResultCode.FETCH_USERINFO_ERROR);
        }

        String phone = userInfo.getPhone();
        int code = SendSMSUtil.sendYzCode(phone);
//        int code = 666666;
        System.out.println("code:"+code);
        if (code !=0){
            System.out.println("phone:"+phone);
            System.out.println("code:"+code);
            redisTemplate.opsForValue().set("phone:"+phone,phone,7,TimeUnit.DAYS);
            redisTemplate.opsForValue().set("code:"+code, String.valueOf(code),7,TimeUnit.DAYS);
        }else {
            throw new ServiceException(ResultCode.INCORRECT_USERNAME_OR_PASSWORD);
        }
        return Result.ok();
    }

    /**
     * 单点登录
     * @param request
     * @return
     */
    @ApiOperation("单点登录")
    @GetMapping("/info")
    public Result userInfo(HttpServletRequest request){
        String token = request.getHeader("token");
        log.warn("key: {}", "user:login:" + token);
        String userInfo = redisTemplate.opsForValue().get("user:login:" + token);
        if (userInfo == null) {
            return Result.fail(ResultCode.FETCH_USERINFO_ERROR);
        }
        return Result.ok(JSON.parseObject(userInfo, UserBaseDetailVo.class));
    }


    private String getMD5Password(String password){
        log.warn("原始密码：{}", password);
        for (int i = 0; i < 3; i++ ) {
            password = DigestUtils.md5DigestAsHex((password).getBytes()).toUpperCase();
        }
        return password;
    }
}
